from paste.registry import RegistryManager, StackedObjectProxy
__all__ = ['DispatchingConfig',
 'CONFIG',
 'ConfigMiddleware']

class DispatchingConfig(StackedObjectProxy):

    def __init__(self, name = 'DispatchingConfig'):
        super(DispatchingConfig, self).__init__(name=name)
        self.__dict__['_process_configs'] = []



    def push_thread_config(self, conf):
        self._push_object(conf)



    def pop_thread_config(self, conf = None):
        self._pop_object(conf)



    def push_process_config(self, conf):
        self._process_configs.append(conf)



    def pop_process_config(self, conf = None):
        self._pop_from(self._process_configs, conf)



    def _pop_from(self, lst, conf):
        popped = lst.pop()
        if ((conf is not None) and (popped is not conf)):
            raise AssertionError(('The config popped (%s) is not the same as the config expected (%s)' % (popped, conf)))



    def _current_obj(self):
        try:
            return super(DispatchingConfig, self)._current_obj()
        except TypeError:
            if self._process_configs:
                return self._process_configs[-1]
            raise AttributeError('No configuration has been registered for this process or thread')


    current = current_conf = _current_obj

CONFIG = DispatchingConfig()
no_config = object()

class ConfigMiddleware(RegistryManager):

    def __init__(self, application, config, dispatching_config = CONFIG, environ_key = 'paste.config'):

        def register_config(environ, start_response):
            popped_config = environ.get(environ_key, no_config)
            current_config = environ[environ_key] = config.copy()
            environ['paste.registry'].register(dispatching_config, current_config)
            try:
                app_iter = application(environ, start_response)

            finally:
                if (popped_config is no_config):
                    environ.pop(environ_key, None)
                else:
                    environ[environ_key] = popped_config

            return app_iter


        super(self.__class__, self).__init__(register_config)




def make_config_filter(app, global_conf, **local_conf):
    conf = global_conf.copy()
    conf.update(local_conf)
    return ConfigMiddleware(app, conf)


make_config_middleware = ConfigMiddleware.__doc__

